package bubbleindex;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 *
 * @author t
 */
public class noGPU {
    
    /**
     * 
     * @param DAILY_DATA_SIZE
     * @param NUMBER_OF_INDICES 
     */
    public static void Create(int DAILY_DATA_SIZE, int NUMBER_OF_INDICES) {
        LombScargle.Initialize();
        for (int i = 0; i < NUMBER_OF_INDICES; i++){
            try {
                BuildIndex.Stop = false;
                BuildIndex.ResultList = new ArrayList<>();
                List<String> DateList = new ArrayList<>();
                List<String> DataList = new ArrayList<>();
            
                BubbleIndex.PreviousFilePath = Indices.userDir + "ProgramData" + 
                        Indices.filePathSymbol + BubbleIndex.CategoryName + Indices.filePathSymbol + 
                        BubbleIndex.SelectionName + Indices.filePathSymbol + BubbleIndex.SelectionName +
                        Integer.toString(BubbleIndex.BacktestDayLengths[i]) + "days.csv";
            
		if (DAILY_DATA_SIZE - BubbleIndex.BacktestDayLengths[i] <= 1) {
                    BuildIndex.Stop = true;
		}

		int START_INDEX;

                if (InputData.checkForFile(BubbleIndex.PreviousFilePath)) {

                InputData.ReadValues(BubbleIndex.PreviousFilePath, DataList, 
                        DateList, true, true);
				
                int UpdateLength = BubbleIndex.DailyPriceDateList.size() - BuildIndex.updateDateMatch(DateList) - 1;
		
                if (BuildIndex.Stop) {
                    System.out.println("Dates in the previous file: " + 
                            BubbleIndex.PreviousFilePath + " do not match. Code 028.");
                    BubbleIndex.displayOutput("Dates in the previous file: " + 
                            BubbleIndex.PreviousFilePath + " do not match.", false);
                    break;
                }
                
                START_INDEX = DAILY_DATA_SIZE - 
                    BubbleIndex.BacktestDayLengths[i] - UpdateLength;   
		}
			
		else {
                    START_INDEX = 0;         
                }
           
                final int numBatches = (int) Math.ceil((DAILY_DATA_SIZE - BubbleIndex.BacktestDayLengths[i] - START_INDEX) / 500.0);
                        
                for (int batch = 0; batch < numBatches; batch++) {
                    int batchStartIndex = batch * 500 + START_INDEX;
                    int batchEndIndex = (batch + 1) * 500 + START_INDEX;
                    ExecutorService executor = Executors.newFixedThreadPool(BubbleIndex.ThreadNumber);

                    List<Callable<Float>> callables = new ArrayList<>();

                    createCallables(callables, batchStartIndex, Math.min(DAILY_DATA_SIZE - BubbleIndex.BacktestDayLengths[i], batchEndIndex), i);

                    List<Future<Float>> results = executor.invokeAll(callables);

                    for (Future<Float> futures : results) {
                        BuildIndex.ResultList.add(futures.get());
                    }

                    executor.shutdown();
                }

		if (!BuildIndex.Stop) {
                    
                    String Name = BubbleIndex.SelectionName + 
                        BubbleIndex.BacktestDayLengths[i] + "days.csv";

                    ExportData.WriteCSV(BuildIndex.ResultList, DAILY_DATA_SIZE - BubbleIndex.BacktestDayLengths[i], 
			Name, InputData.checkForFile(BubbleIndex.PreviousFilePath));
                }
                
            } catch (IOException | InterruptedException | ExecutionException ex) {
                System.out.println("Exception. Code 015.");
            }
        }   
    }
    
    /**
     * 
     * @param callables
     * @param START
     * @param SIZE
     * @param INDEX 
     */
    private static void createCallables(List<Callable<Float>> callables, int START, int SIZE, int INDEX) {

        for (int j = START; j < SIZE; j++) {
            callables.add(new MyCPUCallable(j, BubbleIndex.BacktestDayLengths[INDEX]));   
        }                   
    }
}